Avastage võimsad TypeScripti alternatiivid enumitele: konstandi väited ja liittüübid. Õppige, millal kasutada kumbagi robustse ja hooldatava koodi loomiseks.
Enumitest kaugemale: TypeScripti konstandi väited vs. liittüübid
TypeScriptiga staatiliselt tüübitud JavaScripti maailmas on enumid pikka aega olnud peamine valik fikseeritud nimetatud konstantide kogumi esitamiseks. Need pakuvad selget ja loetavat viisi seotud väärtuste kogumi määratlemiseks. Projektide kasvades ja arenedes otsivad arendajad aga sageli paindlikumaid ja mõnikord ka parema jõudlusega alternatiive. Kaks võimsat alternatiivi, mis sageli esile kerkivad, on konstandi väited ja liittüübid. See postitus käsitleb nende alternatiivide kasutamise nüansse traditsiooniliste enumite asemel, pakkudes praktilisi näiteid ja juhendades teid, millal millist valida.
Traditsiooniliste TypeScripti enumite mõistmine
Enne alternatiivide uurimist on oluline kindlalt mõista, kuidas standardne TypeScripti enum töötab. Enumid võimaldavad teil määratleda nimetatud numbri- või stringikonstantide kogumi. Need võivad olla numbrilised (vaikimisi) või stringipõhised.
Numbrilised enumid
Vaikimisi omistatakse enumi liikmetele numbrilised väärtused alates 0-st.
enum DirectionNumeric {
Up,
Down,
Left,
Right
}
let myDirection: DirectionNumeric = DirectionNumeric.Up;
console.log(myDirection); // Output: 0
Saate määrata ka selgesõnaliselt numbrilisi väärtusi.
enum StatusCode {
Success = 200,
NotFound = 404,
InternalError = 500
}
let responseStatus: StatusCode = StatusCode.Success;
console.log(responseStatus); // Output: 200
Stringi enumid
Stringi enumeid eelistatakse sageli tänu paremale silumiskogemusele, kuna liikmete nimed säilivad kompileeritud JavaScriptis.
enum ColorString {
Red = "RED",
Green = "GREEN",
Blue = "BLUE"
}
let favoriteColor: ColorString = ColorString.Blue;
console.log(favoriteColor); // Output: "BLUE"
Enumite lisakulu
Kuigi enumid on mugavad, kaasneb nendega väike lisakulu. JavaScripti kompileerimisel teisendatakse TypeScripti enumid objektideks, millel on sageli pöördkujutised (nt numbrilise väärtuse tagasikujutamine enumi nimele). See võib olla kasulik, kuid see suurendab ka paketi suurust ja ei pruugi alati vajalik olla.
Mõelge sellele lihtsale stringi enumile:
enum Status {
Pending = "PENDING",
Processing = "PROCESSING",
Completed = "COMPLETED"
}
JavaScriptis võib see muutuda millekski selliseks:
var Status;
(function (Status) {
Status["Pending"] = "PENDING";
Status["Processing"] = "PROCESSING";
Status["Completed"] = "COMPLETED";
})(Status || (Status = {}));
Lihtsate, ainult lugemiseks mõeldud konstantide kogumite puhul võib see genereeritud kood tunduda veidi liigne.
Alternatiiv 1: Konstandi väited
Konstandi väited on võimas TypeScripti funktsioon, mis võimaldab kompilaatorile öelda, et ta järeldaks väärtuse jaoks kõige spetsiifilisema võimaliku tüübi. Kui neid kasutatakse massiivide või objektidega, mis on mõeldud fikseeritud väärtuste kogumi esitamiseks, võivad need olla kergekaaluline alternatiiv enumitele.
Konstandi väited massiividega
Saate luua stringiliteraalidest massiivi ja seejärel kasutada const väidet, et muuta selle tüüp muutumatuks ja selle elemendid literaaltüüpideks.
const statusArray = ["PENDING", "PROCESSING", "COMPLETED"] as const;
type StatusType = typeof statusArray[number];
let currentStatus: StatusType = "PROCESSING";
// currentStatus = "FAILED"; // Error: Type '"FAILED"' is not assignable to type 'StatusType'.
function processStatus(status: StatusType) {
console.log(`Processing status: ${status}`);
}
processStatus("COMPLETED");
Mõistame, mis siin toimub:
as const: See väide käsib TypeScriptil käsitleda massiivi ainult lugemiseks ja järeldada selle elementidele kõige spetsiifilisemaid literaaltüüpe. Nii et `string[]` asemel muutub tüübiks `readonly ["PENDING", "PROCESSING", "COMPLETED"]`.typeof statusArray[number]: See on kaardistatud tüüp. See itereerib üle kõikidestatusArrayindeksite ja eraldab nende literaaltüübid.numberindeksiallkiri ütleb sisuliselt "anna mulle mis tahes selle massiivi elemendi tüüp". Tulemuseks on liittüüp:"PENDING" | "PROCESSING" | "COMPLETED".
See lähenemine pakub tüübikindlust, mis sarnaneb stringi enumitele, kuid genereerib minimaalselt JavaScripti. statusArray ise jääb JavaScriptis stringimassiiviks.
Konstandi väited objektidega
Konstandi väited on veelgi võimsamad, kui neid rakendada objektidele. Saate määratleda objekti, kus võtmed esindavad teie nimetatud konstante ja väärtused on literaalstringid või numbrid.
const userRoles = {
Admin: "ADMIN",
Editor: "EDITOR",
Viewer: "VIEWER"
} as const;
type UserRole = typeof userRoles[keyof typeof userRoles];
let currentUserRole: UserRole = "EDITOR";
// currentUserRole = "GUEST"; // Error: Type '"GUEST"' is not assignable to type 'UserRole'.
function displayRole(role: UserRole) {
console.log(`User role is: ${role}`);
}
displayRole(userRoles.Admin); // Valid
displayRole("EDITOR"); // Valid
Selles objekti näites:
as const: See väide muudab kogu objekti ainult lugemiseks. Veelgi olulisem on see, et see järeldab literaaltüübid kõikide omaduste väärtustele (nt"ADMIN"`string`i asemel) ja muudab omadused ise ainult lugemiseks.keyof typeof userRoles: Selle avaldise tulemuseks onuserRolesobjekti võtmete liit, mis on"Admin" | "Editor" | "Viewer".typeof userRoles[keyof typeof userRoles]: See on otsingutüüp. See võtab võtmete liidu ja kasutab seda vastavate väärtuste otsimiseksuserRolestüübis. Selle tulemuseks on väärtuste liit:"ADMIN" | "EDITOR" | "VIEWER", mis on meie soovitud tüüp rollide jaoks.
userRoles JavaScripti väljund on tavaline JavaScripti objekt:
var userRoles = {
Admin: "ADMIN",
Editor: "EDITOR",
Viewer: "VIEWER"
};
See on oluliselt kergem kui tĂĽĂĽpiline enum.
Millal kasutada konstandi väiteid
- Ainult lugemiseks konstandid: Kui vajate fikseeritud hulka stringi- või numbri literaale, mis ei tohiks käitusajal muutuda.
- Minimaalne JavaScripti väljund: Kui teid huvitab paketi suurus ja soovite oma konstantide jaoks kõige jõudluslikumat käitusaja esitust.
- Objektilaadne struktuur: Kui eelistate võtme-väärtuse paaride loetavust, sarnaselt sellele, kuidas te võiksite andmeid või konfiguratsiooni struktureerida.
- Stringipõhised kogumid: Eriti kasulik olekute, tüüpide või kategooriate esitamiseks, mida on kõige parem identifitseerida kirjeldavate stringidega.
Alternatiiv 2: LiittĂĽĂĽbid
Liittüübid võimaldavad deklareerida, et muutuja võib sisaldada ühte mitmest tüübist väärtust. Koos literaaltüüpidega (stringi-, numbri-, boolean-literaalid) moodustavad nad võimsa viisi lubatud väärtuste kogumi määratlemiseks, ilma et oleks vaja kogumi enda jaoks selgesõnalist konstandi deklaratsiooni.
LiittĂĽĂĽbid stringi literaalidega
Saate otse määratleda stringiliteraalide liidu.
type TrafficLightColor = "RED" | "YELLOW" | "GREEN";
let currentLight: TrafficLightColor = "YELLOW";
// currentLight = "BLUE"; // Error: Type '"BLUE"' is not assignable to type 'TrafficLightColor'.
function changeLight(color: TrafficLightColor) {
console.log(`Changing light to: ${color}`);
}
changeLight("RED");
// changeLight("REDDY"); // Error
See on kõige otsesem ja sageli kõige lühem viis lubatud stringiväärtuste kogumi määratlemiseks.
LiittĂĽĂĽbid numbri literaalidega
Sarnaselt saate kasutada numbri literaale.
type HttpStatusCode = 200 | 400 | 404 | 500;
let responseCode: HttpStatusCode = 404;
// responseCode = 201; // Error: Type '201' is not assignable to type 'HttpStatusCode'.
function handleResponse(code: HttpStatusCode) {
if (code === 200) {
console.log("Success!");
} else {
console.log(`Error code: ${code}`);
}
}
handleResponse(500);
Millal kasutada liittĂĽĂĽpe
- Lihtsad, otsesed kogumid: Kui lubatud väärtuste kogum on väike, selge ja ei vaja kirjeldavaid võtmeid peale väärtuste endi.
- Kaudsed konstandid: Kui te ei pea kogumi enda jaoks viitama nimetatud konstandile, vaid kasutate otse literaalväärtusi.
- Maksimaalne konkreetsus: Lihtsamate stsenaariumide puhul, kus spetsiaalse objekti või massiivi määratlemine tundub liigne.
- Funktsiooniparameetrid/tagastustüübid: Suurepärane funktsioonide vastuvõetavate stringi- või numbriväljundite/sisendite täpse kogumi määratlemiseks.
Enumite, konstandi väidete ja liittüüpide võrdlus
Võtame kokku peamised erinevused ja kasutusjuhud:
Käitusaja käitumine
- Enumid: Genereerivad JavaScripti objekte, potentsiaalselt pöördkujutistega.
- Konstandi väited (massiivid/objektid): Genereerivad tavalisi JavaScripti massiive või objekte. Tüübiteave kustutatakse käitusajal, kuid andmestruktuur säilib.
- Liittüübid (literaalidega): Liidul endal puudub käitusaja esitus. Väärtused on lihtsalt literaalid. Tüübikontroll toimub puhtalt kompileerimisajal.
Loetavus ja väljendusrikkus
- Enumid: Suur loetavus, eriti kirjeldavate nimedega. Võivad olla verbaalsemad.
- Konstandi väited (objektid): Hea loetavus võtme-väärtuse paaride kaudu, imiteerides konfiguratsioone või seadeid.
- Konstandi väited (massiivid): Vähem loetav nimetatud konstantide esitamiseks, pigem lihtsalt järjestatud väärtuste loendi jaoks.
- Liittüübid: Väga konkreetsed. Loetavus sõltub literaalväärtuste endi selgusest.
TĂĽĂĽbiohutus
- Kõik kolm lähenemist pakuvad tugevat tüübikindlust. Need tagavad, et muutujatele saab määrata või funktsioonidele edastada ainult kehtivaid, eelnevalt määratletud väärtusi.
Paketi suurus
- Enumid: Üldiselt suurimad genereeritud JavaScripti objektide tõttu.
- Konstandi väited: Väiksemad kui enumid, kuna need toodavad lihtsaid andmestruktuure.
- Liittüübid: Kõige väiksemad, kuna nad ei genereeri tüübi jaoks spetsiifilist käitusaja andmestruktuuri, tuginedes ainult literaalväärtustele.
Kasutusjuhtude maatriks
Siin on kiire juhend:
| Omadus | TypeScripti Enum | Konstandi väide (objekt) | Konstandi väide (massiiv) | Liittüüp (literaalid) |
|---|---|---|---|---|
| Käitusaja väljund | JS-objekt (pöördkujutisega) | Tavaline JS-objekt | Tavaline JS-massiiv | Puudub (ainult literaalväärtused) |
| Loetavus (nimetatud konstandid) | Kõrge | Kõrge | Keskmine | Madal (väärtused on nimed) |
| Paketi suurus | Suurim | Keskmine | Keskmine | Väikseim |
| Paindlikkus | Hea | Hea | Hea | Suurepärane (lihtsate kogumite puhul) |
| Tavaline kasutus | Olekud, olekukoodid, kategooriad | Konfiguratsioon, rollide määratlused, funktsionaalsuslipud | Järjestatud muutumatute väärtuste loendid | Funktsiooniparameetrid, lihtsad piiratud väärtused |
Praktilised näited ja parimad tavad
Näide 1: API olekukoodide esitamine
Enum:
enum ApiStatus {
Success = "SUCCESS",
Error = "ERROR",
Pending = "PENDING"
}
function handleApiResponse(status: ApiStatus) {
// ... loogika ...
}
Konstandi väide (objekt):
const apiStatusCodes = {
SUCCESS: "SUCCESS",
ERROR: "ERROR",
PENDING: "PENDING"
} as const;
type ApiStatus = typeof apiStatusCodes[keyof typeof apiStatusCodes];
function handleApiResponse(status: ApiStatus) {
// ... loogika ...
}
LiittĂĽĂĽp:
type ApiStatus = "SUCCESS" | "ERROR" | "PENDING";
function handleApiResponse(status: ApiStatus) {
// ... loogika ...
}
Soovitus: Selle stsenaariumi puhul on liittüüp sageli kõige konkreetsem ja tõhusam. Literaalväärtused ise on piisavalt kirjeldavad. Kui teil oleks vaja iga olekuga seostada lisametainfot (nt kasutajasõbralik sõnum), oleks parem valik konstandi väite objekt.
Näide 2: Kasutajarollide määratlemine
Enum:
enum UserRoleEnum {
Admin = "ADMIN",
Moderator = "MODERATOR",
User = "USER"
}
function getUserPermissions(role: UserRoleEnum) {
// ... loogika ...
}
Konstandi väide (objekt):
const userRolesObject = {
Admin: "ADMIN",
Moderator: "MODERATOR",
User: "USER"
} as const;
type UserRole = typeof userRolesObject[keyof typeof userRolesObject];
function getUserPermissions(role: UserRole) {
// ... loogika ...
}
LiittĂĽĂĽp:
type UserRole = "ADMIN" | "MODERATOR" | "USER";
function getUserPermissions(role: UserRole) {
// ... loogika ...
}
Soovitus: Konstandi väite objekt pakub siin head tasakaalu. See annab selged võtme-väärtuse paarid (nt userRolesObject.Admin), mis võivad parandada loetavust rollidele viitamisel, olles samal ajal siiski jõudluslik. Liittüüp on samuti väga tugev kandidaat, kui piisavad on otsesed stringiliteraalid.
Näide 3: Konfiguratsioonivalikute esitamine
Kujutage ette globaalse rakenduse konfiguratsiooni objekti, millel võivad olla erinevad teemad.
Enum:
enum Theme {
Light = "light",
Dark = "dark",
System = "system"
}
interface AppConfig {
theme: Theme;
// ... muud konfiguratsioonivalikud ...
}
Konstandi väide (objekt):
const themes = {
Light: "light",
Dark: "dark",
System: "system"
} as const;
type Theme = typeof themes[keyof typeof themes];
interface AppConfig {
theme: Theme;
// ... muud konfiguratsioonivalikud ...
}
LiittĂĽĂĽp:
type Theme = "light" | "dark" | "system";
interface AppConfig {
theme: Theme;
// ... muud konfiguratsioonivalikud ...
}
Soovitus: Konfiguratsiooniseadete, nagu teemade, puhul on konstandi väite objekt sageli ideaalne. See määratleb selgelt saadaolevad valikud ja nende vastavad stringiväärtused. Võtmed (Light, Dark, System) on kirjeldavad ja vastavad otse väärtustele, muutes konfiguratsioonikoodi väga arusaadavaks.
Õige tööriista valimine
Otsus TypeScripti enumite, konstandi väidete ja liittüüpide vahel ei ole alati mustvalge. See taandub sageli kompromissile käitusaja jõudluse, paketi suuruse ning koodi loetavuse/väljendusrikkuse vahel.
- Valige liittüübid, kui vajate lihtsat, piiratud stringi- või numbri literaalide kogumit ja soovite maksimaalset konkreetsust. Need sobivad suurepäraselt funktsioonide allkirjade ja põhiliste väärtuspiirangute jaoks.
- Valige konstandi väited (objektidega), kui soovite struktureeritumat ja loetavamat viisi nimetatud konstantide määratlemiseks, sarnaselt enumile, kuid oluliselt väiksema käitusaja lisakuluga. See sobib suurepäraselt konfiguratsiooni, rollide või mis tahes kogumi jaoks, kus võtmed lisavad olulist tähendust.
- Valige konstandi väited (massiividega), kui vajate lihtsalt muutumatut järjestatud väärtuste loendit ja otsene juurdepääs indeksi kaudu on olulisem kui nimetatud võtmed.
- Kaaluge TypeScripti enumeid, kui vajate nende spetsiifilisi funktsioone, nagu pöördkujutamine (kuigi see on kaasaegses arenduses harvem) või kui teie meeskonnal on tugev eelistus ja jõudlusmõju teie projekti jaoks on tühine.
Paljudes kaasaegsetes TypeScripti projektides kaldutakse traditsiooniliste enumite asemel kasutama konstandi väiteid ja liittüüpe, eriti stringipõhiste konstantide puhul, nende paremate jõudlusomaduste ja sageli lihtsama JavaScripti väljundi tõttu.
Globaalsed kaalutlused
Rakenduste arendamisel globaalsele publikule on olulised järjepidevad ja prognoositavad konstantide määratlused. Kõik arutatud valikud (enumid, konstandi väited, liittüübid) aitavad kaasa sellele järjepidevusele, jõustades tüübikindluse erinevates keskkondades ja arendajate lokaatides.
- Järjepidevus: Sõltumata valitud meetodist on võtmeks järjepidevus teie projektis. Kui otsustate rollide jaoks kasutada konstandi väite objekte, järgige seda mustrit kogu koodibaasis.
- Rahvusvahelistamine (i18n): Rahvusvahelistatavate siltide või sõnumite määratlemisel kasutage neid tüübikindlaid struktuure, et tagada ainult kehtivate võtmete või identifikaatorite kasutamine. Tegelikke tõlgitud stringe hallatakse eraldi i18n-teekide kaudu. Näiteks kui teil on olekuväli (`status`), mis võib olla "PENDING", "PROCESSING", "COMPLETED", kaardistaks teie i18n-teek need sisemised identifikaatorid lokaliseeritud kuvatekstiks.
- Ajavööndid ja valuutad: Kuigi see ei ole otseselt seotud enumitega, pidage meeles, et selliste väärtuste nagu kuupäevade, kellaaegade või valuutadega tegelemisel aitab TypeScripti tüübisüsteem tagada õige kasutuse, kuid täpseks globaalseks käitlemiseks on tavaliselt vaja väliseid teeke. Näiteks võiks valuuta (
Currency) liittüüp olla määratletud kui "USD" | "EUR" | "GBP", kuid tegelikuks konversiooniloogikaks on vaja spetsiaalseid tööriistu.
Järeldus
TypeScript pakub rikkaliku tööriistakomplekti konstantide haldamiseks. Kuigi enumid on meid hästi teeninud, pakuvad konstandi väited ja liittüübid veenvaid, sageli parema jõudlusega alternatiive. Mõistes nende erinevusi ja valides õige lähenemisviisi vastavalt oma konkreetsetele vajadustele – olgu selleks jõudlus, loetavus või konkreetsus – saate kirjutada robustsema, hooldatavama ja tõhusama TypeScripti koodi, mis skaleerub globaalselt.
Nende alternatiivide omaksvõtmine võib viia väiksemate paketi suurusteni, kiiremate rakendusteni ja prognoositavama arenduskogemuseni teie rahvusvahelisele meeskonnale.